﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Markup;
using System.Windows.Shell;
using Alternet.Common;
using Alternet.Common.Projects.DotNet;
using Alternet.Editor;
using Alternet.Editor.Common;
using Alternet.Editor.Roslyn;
using Alternet.Scripter;
using Alternet.Scripter.Debugger;
using Alternet.Scripter.Debugger.UI;
using Alternet.Scripter.Integration;
using Microsoft.CodeAnalysis;
using OrBitDataModule.Common;

namespace OrBitDataModule.ScripterDebugger

{
    public partial class DebuggerForm : Form, IDebuggerUICommands
    {
        private string UniqueId = string.Empty;
        private string DataProtocolScriptId = string.Empty;
        private string ScriptName = string.Empty;
        private string ScriptCode = string.Empty;
        private string ScriptDescription = string.Empty;


        private IScriptDebugger debugger;

        private DebugCodeEditContainer codeEditContainer;

        private RemoteControlParameters remoteControlParameters;
        private RemoteControlService remoteControlService;

        private readonly string ScriptFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripter.cs");
        private readonly string ScriptRunnerPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ScripterRunner.exe");

        public DebuggerForm()
        {
            InitializeComponent();

            codeEditContainer = new DebugCodeEditContainer(editorsTabControl);
            codeEditContainer.EditorRequested += EditorContainer_EditorRequested;

            debugger = new ScriptDebugger
            {
                ScriptRun = scriptRun,
            };

            //debugger.DebuggerErrorOccured += Debugger_DebuggerErrorOccured;

            debuggerControlToolbar1.Debugger = debugger;
            debuggerControlToolbar1.DebuggerPreStartup += OnDebuggerPreStartup;

            debugMenu1.Debugger = debugger;
            debugMenu1.DebuggerPreStartup += OnDebuggerPreStartup;

            debuggerPanelsTabControl.Debugger = debugger;

            var controller = new DebuggerUIController(this, codeEditContainer);
            controller.Debugger = debugger;

            controller.DebuggerPanels = debuggerPanelsTabControl;
            debuggerPanelsTabControl.Locals.Parent.Text = "局部变量";
            debuggerPanelsTabControl.Output.Parent.Text = "输出";
            debuggerPanelsTabControl.Breakpoints.Parent.Text = "断点";
            debuggerPanelsTabControl.CallStack.Parent.Text = "调用堆栈";
            debuggerPanelsTabControl.Watches.Parent.Text = "监视";
            debuggerPanelsTabControl.Threads.Parent.Text = "线程";
            debuggerPanelsTabControl.Errors.Parent.Text = "错误列表";
            debuggerPanelsTabControl.FindResults.Parent.Text = "查找结果";

            debuggerPanelsTabControl.Output.sslDebug.Text = "调试";
            debuggerPanelsTabControl.Output.sslGeneral.Text = "常规";
            codeEditContainer.Debugger = debugger;
            InitializeDebugger();
            ScaleControls();
            this.FormClosed += (s, e) =>
            {
                if (Debugger.State != DebuggerState.Off)
                    ProcessHelper.TerminateProcessesByFilePath(ScriptRunnerPath);
            };
            mainMenu.Visible = false;
            toolStripLabel1.Text = string.Empty;
        }
        #region 调试部分
        public void LoadScript(string uniqueId, string taskName, string scriptName, string scriptCode, string dataProtocolScriptId, string scriptDescription, string userName, string password)
        {
            CloseFile();
            ClearTempDirectory();
            this.UniqueId = uniqueId;
            this.DataProtocolScriptId = dataProtocolScriptId;
            this.ScriptName = scriptName;
            this.ScriptCode = scriptCode;
            this.ScriptDescription = scriptDescription;

            if (File.Exists(ScriptFilePath))
                File.Delete(ScriptFilePath);
            File.WriteAllText(ScriptFilePath, scriptCode);
            OpenCSFile();
            scriptRun.ScriptSource.WithDefaultReferences();
            //默认添加数据模块dll的引用
            AddReference(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "OrBitDataModule.dll"));
            AddReference("System.Data.dll");
            AddReference("System.Windows.Forms.dll");
            AddReference("Newtonsoft.Json.dll");
            AddReference("netstandard.dll");
            AddReference("System.Text.Json.dll");
            AddReference("System.Text.Encodings.Web.dll");
            AddReference("System.Text.Encoding.CodePages.dll");

            AddLocalReference();
            toolStripLabel1.Text = $"当前调试项目：{taskName},脚本名称：{scriptName}";
        }
        private void AddLocalReference()
        {
            string directory = AppDomain.CurrentDomain.BaseDirectory;
            foreach (string file in Directory.GetFiles(directory, "*.dll").Where(f => f.Length != 36))
            {
                try
                {
                    if (Path.GetFileName(file).StartsWith("System.") && Path.GetFileName(file) != "System.EnterpriseServices.Wrapper.dll")
                    {
                        AddReference(Path.GetFileName(file));
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"加载 {Path.GetFileName(file)} 时出错：{ex.Message}");
                }
            }
        }

        public void AddReference(string dllFilePath)
        {
            if (codeEditContainer.ActiveEditor != null)
                CodeEditExtensions.RegisterAssembly(codeEditContainer.ActiveEditor, "System.Data.dll");
        }

        private void AttachToControlledProcess(string[] codeModules)
        {
            Task.Run(() =>
                debugger.AttachToProcessAsync(
                    remoteControlParameters.ProcessId,
                    new StartDebuggingOptions
                    {
                        MyCodeModules = codeModules,
                    })).Wait();
        }

        protected override void OnClosed(EventArgs e)
        {
            if (Debugger.IsStarted)
                Task.Run(async () => await Debugger.StopDebuggingAsync()).Wait();

            base.OnClosed(e);

            Debugger.ClearTemporaryGeneratedModules();
        }

        protected void RunScriptCore()
        {
            remoteControlService.CompileScript(result =>
            {
                if (result.IsSuccessful)
                    Invoke((Action)(() => remoteControlService.StartScript(() => { })));
                else if (result.Errors.Length > 0)
                    ReportScriptCompilationErrors(result.Errors);
            });
        }

        protected bool CompileCore()
        {
            remoteControlService.CompileScript(result =>
            {
                if (!result.IsSuccessful && result.Errors.Length > 0)
                    ReportScriptCompilationErrors(result.Errors);
            });

            return true;
        }

        protected void StartDebugCore(bool breakOnStart)
        {
            ProcessHelper.TerminateProcessesByFilePath(ScriptRunnerPath);

            remoteControlService = null;

            AttachToRunner();

            //remoteControlService = new RemoteControlService(remoteControlParameters);

            remoteControlService = new RemoteControlService(remoteControlParameters);
            remoteControlService.StartClient();

            remoteControlService.CompileScript(result =>
            {
                if (result.IsSuccessful)
                {
                    var targetAssembly = new[] { result.TargetAssemblyName };
                    //AttachToControlledProcess(remoteControlParameters.CodeModules?.Concat(targetAssembly).ToArray() ?? targetAssembly);
                    AttachToControlledProcess(targetAssembly);
                    Invoke((Action)StartControlledScript);
                }

                if (result.Errors.Length > 0)
                    ReportScriptCompilationErrors(result.Errors);
            });
        }

        private void AttachToRunner()
        {
            remoteControlParameters = null;
            string mainScriptFile = ScriptFilePath;

            string userName = SharedData.LoginUserName;
            string password = SharedData.LoginUserPassword;

            string[] codeModules = GetCodeModules(AppDomain.CurrentDomain.BaseDirectory);
            string[] references = GetDefaultReferences();
            string[] codeFiles = new string[] { mainScriptFile };
            string globalCode = "";
            string ipcPortName = Guid.NewGuid().ToString();
            string ipcObjectUri = Guid.NewGuid().ToString();
            int processId = ProcessHelper.RunProcess(ScriptRunnerPath, $"\"-uniqueId={this.UniqueId}\" \"-userName={userName}\" \"-password={password}\" \"-ipcPortName={ipcPortName}\" \"-ipcObjectUri={ipcObjectUri}\"");
            remoteControlParameters = new RemoteControlParameters(mainScriptFile, codeModules, processId, references, codeFiles, globalCode, ipcPortName, ipcObjectUri);
        }

        private string[] GetDefaultReferences() => "mscorlib,System,System.Core,System.Drawing,System.Windows.Forms".Split(',');

        private string[] GetCodeModules(string path) => Directory.GetFiles(path, "*.dll").Where(f => f.Length == 36).ToArray();


        protected void ReportScriptCompilationErrors(ScriptCompilationDiagnostic[] errors)
        {
            Invoke((Action)(() =>
            {
                debuggerPanelsTabControl.Errors.Clear();
                debuggerPanelsTabControl.Errors.AddCompilerErrors(errors);
            }));
        }


        protected void StopDebugCore()
        {
            Invoke((Action)StopControlledScript);
        }

        protected void LoadStartupFile()
        {
            LoadControlledScript();
        }
        private void LoadControlledScript()
        {
            if (remoteControlService == null)
                return;

            string extension;
            string projectName = null;

            var controlledScriptFile = remoteControlParameters.MainScriptFile;


            extension = Path.GetExtension(controlledScriptFile);


            var controlledScriptCodeFiles = remoteControlParameters.CodeFiles;
            if (controlledScriptCodeFiles != null)
                CodeEditExtensions.RegisterCode(extension, controlledScriptCodeFiles, projectName);

            var references = remoteControlParameters.References;
            if (references != null)
            {
                CodeEditExtensions.RegisterAssemblies(
                    extension,
                    Project.HasProject ? Project.TryResolveAbsolutePaths(references).ToArray() : references.ToArray(),
                    keepExisting: true,
                    projectName: projectName);
            }
        }

        private void StartControlledScript()
        {
            if (remoteControlService != null)
            {
                remoteControlService.StartScript(() =>
                {
                    StopDebug();
                });
            }
        }

        private void StopControlledScript()
        {
            if (remoteControlService != null)
            {
                if (Debugger.State != DebuggerState.Off)
                {
                    Task.Run(async () => await Debugger.StopDebuggingAsync()).Wait();
                    //await Debugger.StopDebuggingAsync();
                    //中断情况下调试端收不到，会卡死
                    //remoteControlService.StopScript();
                }
            }
            remoteControlService?.StopClient();
            ProcessHelper.TerminateProcessesByProcessId(remoteControlParameters.ProcessId);
        }

        #endregion

        #region 默认
        private void OpenCSFile()
        {
            CloseFile();
            codeEditContainer.TryActivateEditor(ScriptFilePath);
            scriptRun.ScriptSource.WithDefaultReferences();
        }

        private void CloseFile() => CloseFile(ScriptFilePath);

        protected DotNetProject Project { get; private set; } = new DotNetProject();
        public StartDebuggingOptions StartDebuggingOptions { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        public void SaveAllModifiedFiles()
        {
            foreach (var edit in codeEditContainer.Editors)
            {
                if (edit.Modified)
                    edit.SaveFile(edit.FileName);
            }
        }

        private void Debugger_DebuggerErrorOccured(object sender, DebuggerErrorOccuredEventArgs e)
        {
            BeginInvoke(new Action(() => MessageBox.Show(this, e.Exception.ToString(), "Debugger Error", MessageBoxButtons.OK, MessageBoxIcon.Error)));
        }

        private void OnDebuggerPreStartup(object sender, EventArgs e)
        {
            SaveAllModifiedFiles();
            SetScriptSource();
        }

        private bool SetScriptSource()
        {
            if (Project.HasProject)
                return true;

            if (codeEditContainer.ActiveEditor != null)
            {
                string fileName = codeEditContainer.ActiveEditor.FileName;
                if (new FileInfo(fileName).Exists)
                {
                    scriptRun.ScriptSource.FromScriptFile(fileName);
                    return true;
                }
            }

            return false;
        }

        private void ScaleControls()
        {
            if (!DisplayScaling.NeedsScaling)
                return;

            splitContainer.SplitterDistance = DisplayScaling.AutoScale(splitContainer.SplitterDistance);
        }

        private void OpenProject(string projectFilePath)
        {
            if (Project != null && Project.HasProject)
                CloseProject(Project);

            Project.Load(projectFilePath);
            scriptRun.ScriptSource.FromScriptProject(Project.ProjectFileName);
            var extension = Project.ProjectExtension;
            CodeEditExtensions.OpenProject(extension, Project);

            if (Project.Files.Count > 0)
            {
                codeEditContainer.TryActivateEditor(Project.Files[0]);
            }

            debuggerPanelsTabControl.Errors.Clear();
        }

        private void CloseProject(DotNetProject project)
        {
            foreach (string fileName in project.Files)
            {
                CloseFile(fileName);
            }

            foreach (string fileName in project.Resources)
            {
                CloseFile(fileName);
            }

            var extension = string.Format(".{0}", project.DefaultExtension);

            CodeEditExtensions.CloseProject(extension, project.ProjectName);
            Project?.Reset();
            scriptRun.ScriptSource?.Reset();
        }

        private void CloseFile(string fileName)
        {
            codeEditContainer.CloseFile(fileName);
            scriptRun.ScriptSource.References.Clear();
            if (codeEditContainer.ActiveEditor != null)
            {
                CodeEditExtensions.UnregisterAssemblies("*.dll");
            }

        }

        private string GetProjectName(string fileName)
        {
            if (Project.HasProject)
            {
                if (Project.Files.Contains(fileName, StringComparer.OrdinalIgnoreCase))
                    return Project.ProjectName;
            }

            return null;
        }

        private void ClearTempDirectory()
        {
            try
            {
                var path = AppDomain.CurrentDomain.BaseDirectory; //scriptRun.ScriptHost.ModulesDirectoryPath;
                if (Directory.Exists(path))
                {
                    string pattern = @"^[a-zA-Z0-9]{32}\.(dll|pdb)$";
                    Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);

                    // 获取目录中的所有文件
                    string[] files = Directory.GetFiles(path);

                    foreach (string file in files)
                    {
                        string fileName = Path.GetFileName(file);
                        if (regex.IsMatch(fileName))
                        {
                            try
                            {
                                File.Delete(file);
                            }
                            catch
                            {
                            }
                        }
                    }
                }
            }
            catch
            {
            }
        }

        private void EditorContainer_EditorRequested(object sender, DebugEditRequestedEventArgs e)
        {
            var edit = new DebugCodeEdit();
            var projectName = GetProjectName(e.FileName);
            edit.SetFileNameAndProject(e.FileName, projectName);
            edit.LoadFile(e.FileName);
            e.DebugEdit = edit;
        }

        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void OpenProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (var dialog = new OpenFileDialog
            {
                Filter = "Project files (*.csproj; *.vbproj)|*.csproj;*.vbproj|All files (*.*)|*.*",
                InitialDirectory = AppDomain.CurrentDomain.BaseDirectory,
            })
            {
                if (dialog.ShowDialog(this) != DialogResult.OK)
                    return;

                OpenProject(dialog.FileName);
            }
        }

        private void CloseProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CloseProject(Project);
        }

        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (var dialog = new OpenFileDialog
            {
                Filter = "C# files (*.cs) |*.cs|Visual Basic files (*.vb) | *.vb|Any files (*.*)|*.*",
                FilterIndex = 1,
                InitialDirectory = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory),
            })
            {
                if (dialog.ShowDialog(this) != DialogResult.OK)
                    return;
                codeEditContainer.TryActivateEditor(dialog.FileName);
            }
        }

        private void SaveMenuItem_Click(object sender, EventArgs e)
        {
            if (codeEditContainer.ActiveEditor != null)
                codeEditContainer.ActiveEditor.SaveFile(codeEditContainer.ActiveEditor.FileName);
        }

        private void CloseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var edit = codeEditContainer.ActiveEditor;
            if (edit != null)
            {
                codeEditContainer.CloseFile(edit.FileName);
                edit.FileName = string.Empty;
            }

            if (!Project.HasProject && codeEditContainer.Editors.Count == 0)
            {
                Project?.Reset();
                scriptRun.ScriptSource?.Reset();
            }
        }

        private void FileToolStripMenuItem_DropDownOpening(object sender, System.EventArgs e)
        {
            closeProjectToolStripMenuItem.Enabled = Project != null && Project.HasProject;
            closeToolStripMenuItem.Enabled = codeEditContainer.ActiveEditor != null;
            saveToolStripMenuItem.Enabled = codeEditContainer.ActiveEditor != null;
        }

        protected IScriptDebugger Debugger
        {
            get
            {
                if (debugger == null)
                {
                    debugger = new ScriptDebugger { ScriptRun = scriptRun };
                    debugger.DebuggingStarted += Debugger_DebuggingStarted;
                    debugger.DebuggingStopped += Debugger_DebuggingStopped;
                    //debugger.DebuggerErrorOccured += Debugger_DebuggerErrorOccured;
                    //debugger.ExecutionResumed += Debugger_ExecutionResumed;
                    //debugger.ExecutionStopped += Debugger_ExecutionStopped;
                    //debugger.StackFrameSwitched += Debugger_StackFrameSwitched;
                    //debugger.ActiveThreadChanged += Debugger_ActiveThreadChanged;

                    //breakpointsControl.Debugger = debugger;
                    //callStackControl.Debugger = debugger;
                    //outputControl.Debugger = debugger;
                    //localsControl.Debugger = debugger;
                    //watchesControl.Debugger = debugger;
                    //errorsControl.Debugger = debugger;
                    //threadsControl.Debugger = debugger;

                    //callStackControl.FramesChanged += CallStack_StackFramesRetrieved;

                    debugger.EventsSyncAction = action => BeginInvoke(action);
                }

                return debugger;
            }
        }

        private void Debugger_DebuggingStarted(object sender, DebuggingStartedEventArgs e)
        {

        }

        private void Debugger_DebuggingStopped(object sender, DebuggingStoppedEventArgs e)
        {

        }

        bool IDebuggerUICommands.PreStartup() => false;

        bool IDebuggerUICommands.Start()
        {
            StartDebugging(false);
            return true;
        }

        bool IDebuggerUICommands.StartWithoutDebug()
        {
            //RunScript();

            return true;
        }

        bool IDebuggerUICommands.Continue()
        {
            if (Debugger.IsStarted)
            {
                //CancelLocalsAndWatchesEvaluation();
                Debugger.Continue();
            }

            return true;
        }

        bool IDebuggerUICommands.Compile()
        {
            //CompileAll();
            CompileCore();
            return true;
        }

        bool IDebuggerUICommands.Stop()
        {
            StopDebug();
            return true;
        }

        bool IDebuggerUICommands.Break()
        {
            Debugger.Break();
            return true;
        }

        bool IDebuggerUICommands.StepInto()
        {
            if (!Debugger.IsStarted)
                StartDebugging(true);
            else
            {
                //CancelLocalsAndWatchesEvaluation();
                Debugger.StepInto();
            }

            return true;
        }

        bool IDebuggerUICommands.StepOver()
        {
            if (!Debugger.IsStarted)
                StartDebugging(true);
            else
            {
                //CancelLocalsAndWatchesEvaluation();
                Debugger.StepOver();
            }

            return true;
        }

        bool IDebuggerUICommands.StepOut()
        {
            //CancelLocalsAndWatchesEvaluation();
            Debugger.StepOut();

            return true;
        }

        bool IDebuggerUICommands.EvaluateExpression()
        {
            //EvaluateExpression();

            return true;
        }

        bool IDebuggerUICommands.EvaluateCurrentException()
        {
            //EvaluateExpression(evaluateCurrentException: true);
            return true;
        }

        bool IDebuggerUICommands.RunToCursor()
        {
            var edit = codeEditContainer.ActiveEditor;
            if (edit == null)
                return false;

            Debugger.SetRunToPositionBreakpoint(new RunToPositionBreakpoint(edit.FileName, edit.CurrentLine + 1));
            StartDebugging(false);

            return true;
        }


        protected void StopDebug()
        {
            //CancelLocalsAndWatchesEvaluation();
            StopDebugCore();
        }


        private bool TryResetDebuggerOnProjectChange()
        {
            if (debugger != null && debugger.IsStarted)
            {
                MessageBox.Show("Please stop debugging session first");
                return false;
            }

            if (debugger != null)
                debugger.Breakpoints.Clear();

            return true;
        }

        private void InitDebugEdit(IDebugEdit edit)
        {
            edit.Debugger = Debugger;
            //edit.BreakpointToggle += DebugEdit_BreakpointToggle;
            //edit.SetNextStatement += DebugEdit_SetNextStatement;
            //edit.AddToWatchClick += DebugEdit_AddToWatchClick;

            if (Debugger.IsStarted)
                edit.ReadOnly = true;
        }

        private void InitializeDebugger()
        {
            debuggerControlToolbar1.Debugger = Debugger;
            debugMenu1.Debugger = Debugger;
            debugMenu1.CommandsListener = debuggerControlToolbar1.CommandsListener = this;
            debugMenu1.AllowedDebuggerCommands |= AllowedDebuggerCommands.RunToCursor;
        }

        private void ActivateWatchesTab()
        {
            //debuggerPanelsTabControl.SelectedTab = watchesTabPage;
        }

        private void LocalsControl_AddToWatchClick(object sender, Alternet.Scripter.Debugger.UI.AddToWatchClickEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Expression))
            {
                //watchesControl.AddWatch(e.Expression, true, true);
                ActivateWatchesTab();
            }
        }

        private void StartDebugging(bool breakOnStart)
        {
            if (Debugger.IsStarted)
            {
                //CancelLocalsAndWatchesEvaluation();
                Debugger.Continue();
            }
            else
            {
                if (Debugger.State == DebuggerState.Startup)
                    return;

                //if (SaveAllModifiedFiles() && SetScriptSource())
                //{
                StartDebugCore(breakOnStart);

                //    errorsControl.Clear();

                //    var errors = scriptRun.ScriptHost.CompilerErrors;
                //    if (errors != null && errors.Length > 0)
                //        errorsControl.AddCompilerErrors(errors);

                //    if (scriptRun.ScriptHost.CompileFailed)
                //        ActivateErrorsTab();
                //}
            }
        }

        private void btn_save_Click(object sender, EventArgs e)
        {

        }

        //private void EvaluateExpression(bool evaluateCurrentException = false)
        //{
        //    var symbol = ActiveSyntaxEdit != null ? ActiveSyntaxEdit.GetSymbolAtCursor() : string.Empty;
        //    using (var dialog = new EvaluateDialog(
        //        EvaluateDialog.CodeCompletionOptions.Custom((s, d, tb) => new EditorCodeCompletionController(s, d, tb)))
        //    {
        //        Debugger = Debugger,
        //        EvaluateCurrentException = evaluateCurrentException,
        //        Expression = symbol,
        //    })
        //    {
        //        dialog.WatchAdded += (o, e) => watchesControl.AddWatch(e.Expression);
        //        dialog.WatchAdded += (o, e) => ActivateWatchesTab();
        //        dialog.ShowDialog();
        //    }
        //}

        //private void ShowRunParametersDialog()
        //{
        //    if (!Project.HasProject)
        //        return;

        //    using (var dialog = new RunParameters() { CommandLineArgs = Project.UserSettings.CommandLineArgs, StartProgram = Project.UserSettings.StartProgram, StartExternalProgram = Project.UserSettings.StartExternalProgram, IsDotnetCore = Project.TargetFramework != null })
        //    {
        //        if (dialog.ShowDialog() == DialogResult.OK)
        //        {
        //            Project.UserSettings.CommandLineArgs = dialog.CommandLineArgs;
        //            Project.UserSettings.StartProgram = dialog.StartProgram;
        //            Project.UserSettings.StartExternalProgram = dialog.StartExternalProgram;
        //            Project.UserSettings.Save();
        //        }
        //    }
        //}

        //private void UpdateDebugButtons()
        //{
        //    var state = Debugger.State;
        //    var hasProject = HasProject();
        //    var isEmpty = !(hasProject | ActiveSyntaxEdit != null);
        //    var isDebuggingStarted = Debugger.IsStarted;
        //    var isDebugging = isDebuggingStarted || state == DebuggerState.Startup;

        //    attachToProcessMenuItem.Enabled = !isDebugging;
        //    startWithoutDebugMenuItem.Enabled = !isEmpty && !isDebugging;
        //    tsbStartWithoutDebug.Enabled = !isEmpty && !isDebugging;
        //    runParametersMenuItem.Enabled = !isEmpty & !isDebugging && hasProject;
        //}

        //private async void UpdateDebugPanels()
        //{
        //    try
        //    {
        //        var selectedTab = bottomTabControl.SelectedTab;
        //        if (selectedTab == callStackTabPage)
        //        {
        //            if (Debugger.IsStarted)
        //                callStackControl.SetFrames((await Debugger.GetStackFramesAsync()).Frames);
        //        }
        //        else if (selectedTab == localsTabPage)
        //        {
        //            if (Debugger.IsStarted)
        //                localsControl.EvaluateVariables((await Debugger.GetVariablesInScopeAsync()).VariableNames);
        //        }
        //        else if (selectedTab == watchesTabPage)
        //        {
        //            watchesControl.EvaluateWatchExpressions();
        //        }
        //        else if (selectedTab == threadsTabPage)
        //        {
        //            if (Debugger.IsStarted)
        //                threadsControl.SetThreads((await Debugger.GetThreadsAsync()).Threads);
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        MessageBox.Show("Error while updating debugger panels: " + e);
        //    }
        //}

        //private void CallStack_StackFramesRetrieved(object sender, EventArgs e)
        //{
        //    if (switchToTopUserStackFrameNeeded)
        //    {
        //        switchToTopUserStackFrameNeeded = false;
        //        callStackControl.TrySwitchToTopUserStackFrame();
        //    }
        //}

        //private void SetAllEditorsReadOnlyValue(bool readOnly)
        //{
        //    foreach (TabPage tabPage in editorsTabControl.TabPages)
        //    {
        //        var edit = GetEditor(tabPage);
        //        if (edit != null)
        //            edit.ReadOnly = readOnly;
        //    }
        //}

        //private void Debugger_DebuggingStarted(object sender, DebuggingStartedEventArgs e)
        //{
        //    executionPosition = null;
        //    UpdateDebugButtons();
        //    SetAllEditorsReadOnlyValue(true);
        //}




        //private void Debugger_ExecutionStopped(object sender, ExecutionStoppedEventArgs e)
        //{
        //    UpdateDebugButtons();

        //    Activate();
        //    UpdateDebugPanels();

        //    ClearExecutionPosition();

        //    executionPosition = e.Position;

        //    if (e.Position != null && !string.IsNullOrEmpty(e.Position.File))
        //    {
        //        var edit = OpenFile(e.Position.File);
        //        if (edit != null)
        //            ((IDebugEdit)edit).ExecutionStopped(e.Position);
        //    }

        //    if (e.StopReason == ExecutionStopReason.Exception || e.StopReason == ExecutionStopReason.UnhandledException)
        //        DisplayDebuggerException(e);
        //}

        //private void DisplayDebuggerException(ExecutionStoppedEventArgs e)
        //{
        //    var str = $"{e.Exception.ExceptionType}\n{e.Exception.Message}";
        //    using (var dlg = new DebuggerException(Debugger, str))
        //    {
        //        dlg.Text = e.StopReason == ExecutionStopReason.UnhandledException ? StringConsts.UnhandledException : StringConsts.DebuggerException;
        //        dlg.ExceptionEvaluationExpression = e.Exception.ExceptionEvaluationExpression;
        //        dlg.OnEvaluate += Dlg_OnEvaluate;
        //        DialogResult result = dlg.ShowDialog();
        //    }
        //}

        //private void Dlg_OnEvaluate(object sender, EventArgs e)
        //{
        //    EvaluateExpression(true);
        //}

        //private void Debugger_StackFrameSwitched(object sender, StackFrameSwitchedEventArgs e)
        //{
        //    if (e.Frame.Line == null)
        //        return;

        //    if (string.IsNullOrEmpty(e.ErrorMessage))
        //    {
        //        ClearStackFrame();
        //        stackFrame = e.Frame;

        //        var edit = OpenFile(e.Frame.File);
        //        if (edit != null)
        //        {
        //            (edit as IDebugEdit).SwitchStackFrame(e.Frame, executionPosition);
        //            edit.Focus();
        //        }
        //    }
        //    else
        //        MessageBox.Show(e.ErrorMessage);
        //}

        //private async void Debugger_ActiveThreadChanged(object sender, ActiveThreadChangedEventArgs e)
        //{
        //    if (e.ActivatedThread == null)
        //        return;

        //    if (string.IsNullOrEmpty(e.ErrorMessage))
        //    {
        //        switchToTopUserStackFrameNeeded = true;
        //        ActivateCallStackTab();
        //        try
        //        {
        //            callStackControl.SetFrames((await Debugger.GetStackFramesAsync()).Frames);
        //        }
        //        catch (Exception ex)
        //        {
        //            MessageBox.Show("Error while retrieving stack frames: " + ex);
        //        }
        //    }
        //    else
        //        MessageBox.Show(e.ErrorMessage);
        //}

        //private void ActivateCallStackTab()
        //{
        //    bottomTabControl.SelectedTab = callStackTabPage;
        //}

        //private void Debugger_ExecutionResumed(object sender, ExecutionResumedEventArgs e)
        //{
        //    UpdateDebugButtons();
        //    ClearExecutionPosition();
        //    ClearStackFrame();
        //}

        //private void ClearExecutionPosition()
        //{
        //    if (executionPosition != null)
        //    {
        //        var edit = FindFile(executionPosition.File);
        //        if (edit != null)
        //            (edit as IDebugEdit).ClearDebugStyles(executionPosition);
        //        executionPosition = null;
        //    }
        //}

        //private void ClearStackFrame()
        //{
        //    if (stackFrame != null)
        //    {
        //        var edit = FindFile(stackFrame.File);
        //        if (edit != null)
        //            (edit as IDebugEdit).ClearStackFrame(stackFrame);
        //        stackFrame = null;
        //    }
        //}

        //private void CancelLocalsAndWatchesEvaluation()
        //{
        //    Invoke((Action)(async () =>
        //    {
        //        var selectedTab = bottomTabControl.SelectedTab;
        //        if (selectedTab == localsTabPage)
        //        {
        //            if (Debugger.IsStarted)
        //                await localsControl.CancelEvaluationAsync();
        //        }
        //        else if (selectedTab == watchesTabPage)
        //        {
        //            await watchesControl.CancelEvaluationAsync();
        //        }
        //    }));
        //}

        //private void BottomTabControl_SelectedIndexChanged(object sender, EventArgs e)
        //{
        //    UpdateDebugPanels();
        //}

        //private void CallStackControl_CallStackClick(object sender, Alternet.Scripter.Debugger.UI.CallStackClickEventArgs e)
        //{
        //    if (e.StackFrame != null)
        //    {
        //        var edit = OpenFile(e.StackFrame.File);
        //        if (edit != null)
        //        {
        //            edit.MakeVisible(new Point(0, e.StackFrame.Line.Value - 1), true);
        //            edit.Focus();
        //        }
        //    }
        //}

        //private void BreakpointsControl_BreakpointClick(object sender, BreakpointClickEventArgs e)
        //{
        //    if (e.Breakpoint != null)
        //    {
        //        var edit = OpenFile(e.Breakpoint.FilePath);
        //        if (edit != null)
        //        {
        //            edit.MakeVisible(new Point(0, e.Breakpoint.LineNumber - 1), true);
        //            edit.Focus();
        //        }
        //    }
        //}

        //private void BreakpointsControl_BreakpointStateChanged(object sender, BreakpointChangedEventArgs e)
        //{
        //    var breakpoint = e.Breakpoint;
        //    if (breakpoint != null)
        //    {
        //        var edit = FindFile(breakpoint.FilePath) as IDebugEdit;
        //        if (edit != null)
        //            edit.BreakpointStateChanged(breakpoint);
        //    }
        //}

        //private void BreakpointsControl_BreakpointDeleted(object sender, BreakpointChangedEventArgs e)
        //{
        //    Action<Breakpoint> delete = (Breakpoint breakpoint) =>
        //    {
        //        if (breakpoint != null)
        //        {
        //            var edit = FindFile(breakpoint.FilePath) as IDebugEdit;
        //            if (edit != null)
        //                edit.BreakpointDeleted(breakpoint);
        //        }
        //    };

        //    if (e.Breakpoints != null)
        //    {
        //        foreach (var breakpoint in e.Breakpoints)
        //            delete(breakpoint);
        //    }
        //    else
        //        delete(e.Breakpoint);
        //}

        //private void DebugEdit_BreakpointToggle(object sender, EventArgs e)
        //{
        //    breakpointsControl.UpdateList();
        //}

        //private async void DebugEdit_SetNextStatement(object sender, EventArgs e)
        //{
        //    var line = ActiveSyntaxEdit.CurrentLine + 1;
        //    var result = await debugger.TrySetNextStatementAsync(line);
        //    if (result.IsFailure)
        //        MessageBox.Show("Cannot set next statement to line: " + line + ". " + result.ErrorMessage);
        //}

        //private void DebugEdit_AddToWatchClick(object sender, AddToWatchClickEventArgs e)
        //{
        //    if (!string.IsNullOrEmpty(e.Expression))
        //    {
        //        watchesControl.AddWatch(e.Expression, true, true);
        //        ActivateWatchesTab();
        //    }
        //}

    }
    #endregion


}